<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
<script>
    /**
     * 在使用构造函数时，如果存在成员实例方法，因为方法是一个复杂对象，每次通过构造函数创建一个新的对象时，都会会这个复杂对象（方法）开辟一个新的内存空间存放，这样就会存在内存泄漏的问题
     * 解决：通过讲方法存放到prototype（原型对象上），做到所有对象公用一个内存地址的方法，节省内存
     * 在JS中，每一个构造函数中都会默认有一个prototype，指向另一个对象，这个对象的所有属性和方法，都会被构造函数所拥有
     * 而对于实例的对象，都会默认有一个 __proto__ 属性，该属性指向的就是构造函数中的prototype，二者等价，所以对象可以使用prototype中的方法和属性
     * 方法的查找规则: 首先先看ldh 对象身上是否有 sing 方法,如果有就执行这个对象上的sing
     * 如果么有sing 这个方法,因为有__proto__ 的存在,就去构造函数原型对象prototype身上去查找sing这个方法
     * 注意：不论sing在ldh实例对象上或者是__proto__原型对象上，sing中的this始终指向ldh这个实例对象，因为他是调用者。
     * @param uname
     * @param age
     * @constructor
     */
    // 构造函数中的属性和方法我们称为成员, 成员可以添加
    function Star(uname, age) {
        this.uname = uname;
        this.age = age;
        this.sing = function () {
            console.log('我会唱歌');

        }
    }

    Star.prototype.jump = function () {
        console.log('I can jump')
    };
    var ldh = new Star('刘德华', 18);
    var zxy = new Star('张学友', 20);

    console.dir(Star); //可以查看Star中的prototype对象
    console.log(ldh);
    console.log(ldh.sing === zxy.sing); // false，该方法没有绑定到prototype上，每次实例化对象都会开辟新的内存存储该方法
    console.log(ldh.jump === zxy.jump); // true，该方法有绑定到prototype上，每次实例化对象都会重复使用prototype中的jump
    // 调用的模式和sing一样
    ldh.jump();
    zxy.jump();

    // 对象原型
    // 方法的查找规则: 首先先看ldh 对象身上是否有 sing 方法,如果有就执行这个对象上的sing
    // 如果么有sing 这个方法,因为有__proto__ 的存在,就去构造函数原型对象prototype身上去查找sing这个方法
    console.log(ldh.__proto__ === Star.prototype);// true,二者等价
    console.log("============================");
    console.log(Star.prototype);
    console.log(ldh.__proto__)


</script>
</body>

</html>